#ifndef __TIMER_H__
#define __TIMER_H__

#include <memory>
#include <vector>
#include <set>
#include <shared_mutex>
#include <assert.h>
#include <functional>
#include <mutex>

namespace lzp {
    
class TimerManager;

/**
 * @brief 定时器
 */
class Timer : public std::enable_shared_from_this<Timer> {
    friend class TimerManager;
public:
    /**
     * @brief 取消定时器
     */
    bool cancel();

    /**
     * @brief 将定时器的超时时间刷新为当前时间now+超时时间m_ms
     */
    bool refresh();

    /**
     * @brief 重置定时器时间
     * @param[in] ms 定时器执⾏间隔时间(毫秒)
     * @param[in] from_now 是否从当前时间开始计算
     */
    bool reset(uint64_t ms, bool from_now);

private:
    /**
     * @brief 构造函数
     * @param[in] ms 定时器执⾏间隔时间
     * @param[in] cb 回调函数
     * @param[in] recurring 是否循环
     * @param[in] manager 定时器管理器
     */
    Timer(uint64_t ms, std::function<void()> cb, bool recurring, TimerManager* manager);

private:
    // 是否循环
    bool m_recurring = false;
    // 超时时间
    uint64_t m_ms = 0;
    // 绝对超时时间
    std::chrono::time_point<std::chrono::system_clock> m_next;
    // 超时时触发的回调函数
    std::function<void()> m_cb;
    // 管理此timer的管理器
    TimerManager* m_manager = nullptr;

private:
    /**
     * @brief 定时器⽐较仿函数
     */
    struct Comparator {
        /**
         * @brief ⽐较定时器的智能指针的⼤⼩(按执⾏时间排序)
         * @param[in] lhs 定时器智能指针
         * @param[in] rhs 定时器智能指针
         */
        bool operator()(const std::shared_ptr<Timer>& lhs, const std::shared_ptr<Timer>& rhs) const; 
    };
};

/**
 * @brief 定时器管理器
 */
class TimerManager {
    friend class Timer;

public:
    /**
     * @brief 构造函数
     */
    TimerManager();

    /**
     * @brief 析构函数
     */
    virtual ~TimerManager();

    /**
     * @brief 添加定时器
     * @param[in] ms 定时器执行间隔时间
     * @param[in] cb 定时器回调函数
     * @param[in] recurring 是否循环定时器
     */
    std::shared_ptr<Timer> addTimer(uint64_t ms, std::function<void()> cb, bool recurring = false);

    /**
     * @brief 添加条件定时器
     * @param[in] ms 定时器执⾏间隔时间
     * @param[in] cb 定时器回调函数
     * @param[in] weak_cond 条件
     * @param[in] recurring 是否循环
     */
    std::shared_ptr<Timer> addConditionTimer(uint64_t ms, std::function<void()> cb, std::weak_ptr<void> weak_cond, bool recurring = false);

    /**
     * @brief 如果有定时器超时返回0，没有定时器超时则返回最少还要多久会有定时器超时(毫秒)
     */
    uint64_t getNextTimer();

    /**
     * @brief 获取需要执行的(已超时的定时器)定时器的回调函数列表
     * @param[out] cbs 回调函数数组
     */
    void listExpiredCb(std::vector<std::function<void()>>& cbs);

    /**
     * @brief 是否有定时器
     */
    bool hasTimer();

protected:
    /**
     * @brief 当有新的定时器插⼊到定时器的首部,执行该函数
     */
    virtual void onTimerInsertedAtFront() {};

    /**
     * @brief 将定时器添加到管理器中
     */
    void addTimer(std::shared_ptr<Timer> timer);

private:
    /**
     * @brief 检测服务器时间是否被调后了
     */
    bool detectClockRollover();

private:
    std::shared_mutex m_mutex;
    // 定时器最小堆集合，首个元素就是当前的最小定时器
    std::set<std::shared_ptr<Timer>, Timer::Comparator> m_timers;
    // 是否触发onTimerInsertedAtFront
    bool m_tickled = false;
    // 上次执⾏时间
    std::chrono::time_point<std::chrono::system_clock> m_previouseTime;
};

}

#endif